from django.core.management import BaseCommand, CommandParser
import eventlet
import os
import sys
from apps.tcpserver.server import HandleConnect
from django.utils.log import request_logger
from socket import socket,IPPROTO_TCP,TCP_NODELAY,SOL_SOCKET,SO_SNDBUF
from django.utils.autoreload import run_with_reloader

eventlet.patcher.monkey_patch(thread=False)


class Command(BaseCommand):
    # 最大接受8000个请求
    handle_pool = eventlet.GreenPool(size=8000)
    handle_connect = HandleConnect()

    def add_arguments(self, parser: CommandParser):
        parser.add_argument(
            '-addr',
            default='127.0.0.1',
            type=str,
            required=False
        )
        parser.add_argument(
            '-port',
            default=9001,
            type=int,
            required=False
        )
        parser.add_argument(
            '-process',
            default=2,
            type=int,
            required=False
        )
        parser.add_argument(
            '-reload',
            default=False,
            type=bool,
            required=False
        )

    def handle(self, *args, **options):
        addr = options['addr']
        port = options['port']

        # 使用eventlet  eventlet默认使用epool 后期无需提升性能使用epool
        listen: socket = eventlet.listen((addr, port))
        listen.setsockopt(IPPROTO_TCP,TCP_NODELAY,True)
        # 使用非阻塞 防止redis单独执行事件导致协程之间socket读写混乱
        # listen.setblocking(False)

        request_logger.info('tcp server is listen on %s %s' % (addr, port))
        request_logger.info('main process is %s' % (os.getpid()))

        # 由os.fork启动进程
        # for i in range(options['process'] - 1):
        #     main_process = os.fork()
        #     if not main_process:
        #         break
        #     else:
        #         request_logger.info('%s pid is runing' % (main_process),)

        # 启动redis监听事件函数
        self._start_task_loop()

        def _start():
            while True:

                # sleep 防止所有的请求全部由一个进程接收
                
                try:
                    conn, addr = listen.accept()
                    conn.setsockopt(IPPROTO_TCP,TCP_NODELAY,True)
                    conn.setsockopt(SOL_SOCKET,SO_SNDBUF,0)
                except Exception as e:
                    print(e)
                    eventlet.sleep(0.5)
                    continue

                # 使用非阻塞 防止redis单独执行事件导致协程之间socket读写混乱
                # conn.setblocking(False)
                # 向协程池中执行socket监听函数
                self.handle_pool.spawn(self.handle_connect, conn, addr)
                eventlet.sleep(0.5)

        if options['reload']:
            run_with_reloader(_start)

        else:
            _start()

    def _start_task_loop(self):
        # eventlet.spawn(handle_connect.start_heartbeat)
        eventlet.spawn(self.handle_connect.sub)
